package com.chenxiao.field.fielddemo.advice;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.chenxiao.field.fielddemo.anno.FieldBody;
import com.chenxiao.field.fielddemo.anno.FieldStyle;
import com.chenxiao.field.fielddemo.entity.FieldHttpInputMessage;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.IOException;
import java.lang.reflect.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * @Author: CX
 * @Date: Created in  2023/12/14 15:24
 * @version: v1.0
 * @Description: TODO
 **/
@Order(1)
@ControllerAdvice
@Slf4j
public class FieldRequestBodyAdvice implements RequestBodyAdvice {
    private final ObjectMapper objectMapper;

    public FieldRequestBodyAdvice(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
    private boolean hasAnnotation(AnnotatedElement annotatedElement) {
        return annotatedElement.isAnnotationPresent(FieldStyle.class) || annotatedElement.isAnnotationPresent(FieldBody.class);
    }
    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        if (this.hasAnnotation(methodParameter.getDeclaringClass())) {
            return true;
        }
        Method method = methodParameter.getMethod();
        if (method != null) {
            if (this.hasAnnotation(method)) {
                return true;
            }
            Class<?>[] parameterTypes = method.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                if (this.hasAnnotation(parameterType)) {
                    return true;
                }
            }
        }

        return false;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
        String body = null;
        try {
            body = IoUtil.read(inputMessage.getBody(), Charset.defaultCharset());
        } catch (Exception e) {
            //throw new Exception("Unable to get request body data," + " please check if the sending data body or request method is in compliance with the specification." + " (无法获取请求正文数据，请检查发送数据体或请求方法是否符合规范。)");
        }
        if (!StringUtils.hasText(body)) {
            // throw new DecryptBodyFailException("The request body is NULL or an empty string, so the decryption failed." + " (请求正文为NULL或为空字符串，因此解密失败。)");
        }
        Class<?> targetTypeClass = null;
        try {
            targetTypeClass = Class.forName(targetType.getTypeName());
        } catch (ClassNotFoundException e) {
            // throw new DecryptBodyFailException(e.getMessage());
        }
        body = eachClassField(body, targetTypeClass);

        return new FieldHttpInputMessage(IoUtil.toStream(body, StandardCharsets.UTF_8), inputMessage.getHeaders());
    }
    private String eachClassField(Object body, Class<?> clazz) {
        Field[] declaredFields = clazz.getDeclaredFields();
        JSONObject json = JSONUtil.parseObj(body);
        for (Field field : declaredFields) {
            field.setAccessible(true);
            Class<?> type = field.getType();
            boolean sign = field.isAnnotationPresent(FieldStyle.class);
            if(sign && type.equals(String.class)){
                String fieldValue = (String)json.get(field.getName());
                String decryptResult = fieldValue + "修改值";
                json.set(field.getName(), decryptResult);
             }
        }
        return json.toString();
    }
    private void getAnnotation(AnnotatedElement annotatedElement) {
        if (annotatedElement.isAnnotationPresent(FieldStyle.class)) {
             log.error("命中信息");
        }
    }
    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> aClass) {
      /*  Class<?> targetTypeClass = null;
        try {
            targetTypeClass = Class.forName(targetType.getTypeName());
        } catch (ClassNotFoundException e) {
            // throw new DecryptBodyFailException(e.getMessage());
        }
        Field[] declaredFields = targetTypeClass.getDeclaredFields();
        for (Field field : declaredFields) {
            // 可修改状态
            field.setAccessible(true);
            // 获取数据类型
            Class<?> type = field.getType();
            // 是否需要修改值
            boolean sign = field.isAnnotationPresent(FieldStyle.class);
            // 值的重写
            if (sign && type.equals(String.class)) {
                String fieldValue = (String)ReflectUtil.getFieldValue(body, field);
                String decryptResult = fieldValue + "修改值";
                ReflectUtil.setFieldValue(body, field, decryptResult);
            }
        }*/
       return body;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return null;
    }
}
